//文件名：VehicleOtaMain
//功能：整车OTA入口
//创建时间：2023年3月9日
//作者：dowson
//email：dowson.tseng@gmail.com
#include "string.h"
#include "APP_vehicleOTA.h"
#include "JuzhenJson.h"
#include "SYS_Disk.h"
#include "OtaData.h"
#include "system_init.h"
#include "TigerTallyLock.h"
#include "OtaDataJson.h"
#include "OtaArrayQueueMng.h"
#include "SYS_OTAUpgrade.h"
#include "APP_vehicleOTA.h"
//#include "Rte_ComTypes.h"
#include "CheckFile.h"
#include "Md5.h"
#include "VehicleOta.h"
#include "App_OtaUDSUpgradeMain.h"
#include "VehicleOtaMain.h"
#include "Wdg.h"
#include "4G-HTTP_open_GPS.h"
#include "flash.h"
#include "at32f403a_407_board.h"
#include "app_compiler.h"

#define MD5_CHECK 1
#define UPGRADE_ECU 1
#define OTA_DEBUG_LOG 0
#define OTA_IGNORE_DWL 0
#define OTA_IGNORE_MD5 0
#define OTA_IGNORE_NOTIFY 0
#define OTA_IGNORE_UPGRADE 0
#define MCU_REPLACE_VCU 0

static uint8_t otafileName[3][8] = {
    "parf","drif","otaf"
};

extern AT_RESTATE AT_state;

t_OtaStateManage OtaStateManage; //用于管理当前升级对象
t_VehicleOtaPkg VehicleOtaPkg;  //包含全部升级零部件内容
t_TigerTallyLock TigerTallyLockEcu; //用于管理升级顺序步骤
t_TigerTallyLock TigerTallyLockFileCheck; 
t_TigerTallyLock TigerTallyLockDownload; //用于管理文件下载顺序
t_otaMsgMark otaMsgMark;
//消息接收
t_otaPushMsg otaCmdMsgPkg;
t_otaParamPushMsg otaEcuParamMsgPkg;
//消息上传
t_otaCmdAck otaMsgAckPkg;       //消息接收完成返回
MD5_CTX md5Handle;

//ecu type list
#define ECU_DEVICE_ID_LIST_COUNT 16

#ifdef PARTFROM_AC7
static t_EcuDeviceIdNode const ecuDeviceIdList[ECU_DEVICE_ID_LIST_COUNT] = {
    [0] = {OTA_UNKNOW,OTA_ECU_TYPE_NONE,NONE_ID,"none",NULL},
    [1] = {OTA_BMS,OTA_ECU_TYPE_SOLO,AC7_2101001,"AC7-2101001",Ota_UDSUpgrade_GANFENGBMSSquence_MainLoop},//Diag_BMS_RemoteUpdata_main},
    [2] = {OTA_BMS,OTA_ECU_TYPE_DOUBLE,AC7_2101001C,"AC7-2101001C",Ota_UDSUpgrade_GANFENGBMSSquence_MainLoop},//Diag_BMS_RemoteUpdata_main},
    [3] = {OTA_MCU,OTA_ECU_TYPE_SOLO,AC7_2104010,"AC7-2104010",Ota_UDSUpgradeFor_AnpeiMCUSquence_MainLoop},//Ota_UDSUpgradeFor_AnpeiMCU_MainLoop},
    [4] = {OTA_MCU,OTA_ECU_TYPE_SOLO,AC7_2104010B,"AC7-2104010B",Ota_UDSUpgrade_YingJiLieMCUSquence_MainLoop},//Diag_MCU_RemoteUpdata_main},
    [5] = {OTA_TBOX,OTA_ECU_TYPE_SOLO,AC072_7913010,"AC072-7913010",NULL}
};
#endif

#ifdef PARTFROM_AC8 
static t_EcuDeviceIdNode const ecuDeviceIdList[ECU_DEVICE_ID_LIST_COUNT] = {
    [0] = {OTA_UNKNOW,OTA_ECU_TYPE_NONE,NONE_ID,"none",NULL},
    [1] = {OTA_TBOX,OTA_ECU_TYPE_SOLO,AC08_7913010,"AC08-7913010",NULL},
    [2] = {OTA_BMS,OTA_ECU_TYPE_SOLO,AC08_2101010,"AC08-2101010",Ota_UDSUpgrade_AC08_MainLoop},
#if MCU_REPLACE_VCU
    [3] = {OTA_MCU,OTA_ECU_TYPE_SOLO,AC7_2104010,"AC7-2104010",Ota_UDSUpgrade_AC08_MainLoop},
#else
    [3] = {OTA_VCU,OTA_ECU_TYPE_SOLO,AC08_2108010,"AC08-2108010",Ota_UDSUpgrade_AC08_MainLoop},
#endif
    [4] = {OTA_OBC,OTA_ECU_TYPE_SOLO,AC08_2123030,"AC08-2123030",Ota_UDSUpgrade_AC08OBC_MainLoop}
};
#endif


//t_downloadFileParam downloadEcuFileMsg;


#define OTA_MSG_ACK_MAX_TIME 10  //10秒
void OtaFileDownTest(void);
void OtaFileDownTestReadAll(void);
static uint8_t OTA_OutOTAUpgradeMode(void);
static uint8_t OTA_InUpgradeMode(void);

/**
  * @brief  程序面标志A/B
  */
typedef enum
{
    UPDATE_TYPE_A = 0x41,
    UPDATE_TYPE_B = 0x42,
    UPDATE_TYPE_NONE = 0xff
} update_app_type;
/*检查APP状态*/
static update_app_type Boot_IsAppType(const uint32 i_dataAddr)
{
	update_app_type app_type = (*(update_app_type*)i_dataAddr);
	if ((UPDATE_TYPE_A == app_type)||(UPDATE_TYPE_B == app_type))
	{
		return app_type;
	}else
		return UPDATE_TYPE_NONE;
}
#define TBOX_CUR_TYPE_ADDR	0x0800F800u

//整车升级初始化函数
void VechicleOtaInit(void){
    OtaMsgMarkDataInit(&otaMsgMark);
    OtaQueueMngInit();
    Static_CreatTigerTallyLock(&TigerTallyLockEcu);
    Static_CreatTigerTallyLock(&TigerTallyLockDownload);
    //参数初始化
    OtaStateManage.OtaEcuData.fileData[0].sliceFileCount = 0;
    OtaStateManage.OtaEcuData.fileData[1].sliceFileCount = 0;
    OtaStateManage.OtaEcuData.fileData[2].sliceFileCount = 0;
}

//数据接收与车辆状态检测任务
//说明：该任务在每次启动后会检查一下升级状态同时记录超时时间，主要是考虑用户授权
void VehicleOtaStateCheckMainLoop(void){
    uint8_t ret = 0xff;
    static uint8_t funcStep=0;
    static uint8_t chackTimes=0;
    tTaskItem *thisTask;
    thisTask = FindRunnningItem();
    switch (funcStep)
    {
    case THIRD_STEP0:
        //检查整车状态是否满足升级要求
        //ret = OtaCheckUpgradeCondtion();
        LOG_DBG("--VehicleOtaStateCheckMainLoop\r\n");
        ret = 0;
        if(!ret){
            if (0x01 == ThirdHasBeenCreat(VehicleEcuQueueOTAMainLoop))
                CreatThird("OtaM",To_OS_Slice_Time(100,OS_MSEC),10,VehicleEcuQueueOTAMainLoop);
            //开始升级，关闭无关项状态
            OTA_InUpgradeMode();
            //---------------------------
            funcStep = THIRD_STEP0;
            TaskToClosed(thisTask);
        }else{
            //条件不满足，继续通知用户以达到条件,超时则返回失败
            chackTimes++;
            if(chackTimes>50){
                if(AT_state == AT_IDLE){
                    OtaCmdMsgAckPkgInit(&otaMsgAckPkg);
                    strcpy((char*)(otaMsgAckPkg.data.hv),"null");
                    strcpy((char*)(otaMsgAckPkg.data.sv),"null");
                    OtaServerMsgAck(1,RTE_GEN_OTA_STATE_ACK_ID,true,otaCmdMsgPkg.data.taskId,"ota_up","answer_upgrade","stateErr"); 
                    TaskToClosed(thisTask);
                }else{
                    chackTimes--;
                    printf("ret not zero but AT not IDLE...\r\n");
                }
            }
            funcStep = THIRD_STEP0;
        }
    break;
    }
}


//升级管理任务，包含升级队列管理，以及相应的功能任务触发，该任务触发对应任务之后结束，对应任务结束之后交回控制权
void VehicleEcuQueueOTAMainLoop(void){
    static uint8_t funcStep=0;
    // static uint8_t chackTimes=0;
    static uint8_t resoutDescription[MAX_RETURN_MSG] = {0};
    static uint8_t answerDescription[MAX_RETURN_MSG] = {0};
    tTaskItem *thisTask;
    // uint8_t fileIsOk;
    static uint16_t curdownTimes=20;

    thisTask = FindRunnningItem();
    switch (funcStep)
    {
    case THIRD_STEP0:
        //LOG_DBG("--in VehicleEcuQueueOTAMainLoop\r\n");
        //判断是否还有需要升级的OTA
        if(!OtaQueueMngIsEmpty()){
            OtaQueueMngGet(&OtaStateManage.OtaEcuData);
            //设置该ECU升级参数
            OtaStateManage.cunrrentState = OTA_MSG_GET;
            OtaStateManage.otaDownloadFileParam.downloadState = FILE_NONE;
            OtaStateManage.upgradeState = false;
            OtaStateManage.ecuType = OTA_UNKNOW; 
            OtaStateManage.downloadFileState[OTA_PARAM_FILE].fileIndex = -1;
            OtaStateManage.downloadFileState[OTA_DRIVER_FILE].fileIndex = -1;
            OtaStateManage.downloadFileState[OTA_OTA_FILE].fileIndex = -1;

            LOG_DBG("--get ota queue data:\r\n");
            LOG_DBG(" --targetDevice:%s\r\n",OtaStateManage.OtaEcuData.OtaParam.targetDevice);
            LOG_DBG(" --fatherUrl:%s\r\n",OtaStateManage.OtaEcuData.fileData[2].fatherUrl);
            LOG_DBG(" --fileName:%s\r\n",OtaStateManage.OtaEcuData.fileData[2].fileName);
            LOG_DBG(" --fileSizeSum:%d\r\n",OtaStateManage.OtaEcuData.fileData[2].fileSizeSum);
            LOG_DBG(" --sliceFileCount0:%d\r\n",OtaStateManage.OtaEcuData.fileData[0].sliceFileCount);
            LOG_DBG(" --sliceFileCount1:%d\r\n",OtaStateManage.OtaEcuData.fileData[1].sliceFileCount);
            LOG_DBG(" --sliceFileCount2:%d\r\n",OtaStateManage.OtaEcuData.fileData[2].sliceFileCount);
            LOG_DBG(" --Addr-url:%s\r\n",OtaStateManage.OtaEcuData.fileData[2].Addr[0].sunUrl);
            //获得升级目标类型
            OtaStateManage.ecuType = OtaConversionEcuType(OtaStateManage.OtaEcuData.OtaParam.targetDevice,strlen((const char*)(OtaStateManage.OtaEcuData.OtaParam.targetDevice)));
            LOG_DBG(" --target ecu type:%d\r\n",OtaStateManage.ecuType);
             TigerTallyLockTake(&TigerTallyLockEcu);
            if (0x01 == ThirdHasBeenCreat(VehicleOtaStateFileDownloadMainLoop))
                CreatThird("OtaDd",To_OS_Slice_Time(100,OS_MSEC),10,VehicleOtaStateFileDownloadMainLoop);
            funcStep = THIRD_STEP1;
        }else{
            curdownTimes--;
            if(!curdownTimes){
                if(AT_state == AT_IDLE){
                    curdownTimes = 20;
                    OtaUpgradeEndHandle(TRUE);
                    OtaCmdMsgAckPkgInit(&otaMsgAckPkg);
                    // strcpy(otaMsgAckPkg.data.hv,"hta01");
                    // strcpy(otaMsgAckPkg.data.sv,"sta01");

#if OTA_IGNORE_NOTIFY
                    OtaServerMsgAck(1,RTE_GEN_OTA_STATE_ACK_ID,true,otaCmdMsgPkg.data.taskId,"ota_up","answer_upgrade","stateErr");
#else
                    OtaServerMsgAck(1,RTE_GEN_OTA_STATE_ACK_ID,true,otaCmdMsgPkg.data.taskId,"ota_up","answer_upgrade","ok");
#endif
                    
                    SaveFileAll();
                    OTA_OutOTAUpgradeMode();

                    printf("VehicleEcuQueueOTAMainLoop-OtaStateManage.ecuType:%d\r\n", OtaStateManage.ecuType);

                    if (OTA_TBOX == OtaStateManage.ecuType)
                    {
                        //tbox 直接重启
                        SetUpgradeMark(UPGRADE_OTA);
                        SetSysRunState(SYS_RESTART);
                    }
                    funcStep = THIRD_STEP0;
                    TaskToClosed(thisTask);
                }else{
                    printf("OtaQueueMngIsEmpty but AT NOT IDLE...\r\n");
                    curdownTimes++;
                }
            }
        }
    break;
    case THIRD_STEP1:
        //LOG_DBG(" --check tiger tally back\r\n");
        //检查虎符是否归还
        switch (TigerTallyLockCheck(&TigerTallyLockEcu))
        {
        case TALLY_RETURN_SUCCESS:

            //文件下载成功,缩短时间片周期已加快验签和升级速度
            // TimeSlice_SetSliceTime(SLICE_10MS_TIME);   need to be uncomment
#if MD5_CHECK
            if (0x01 == ThirdHasBeenCreat(VehicleOtaStateFileCheckMainLoop))
                CreatThird("OtaFC",To_OS_Slice_Time(10,OS_MSEC),10,VehicleOtaStateFileCheckMainLoop);
            //交虎符-用于文件验签
            TigerTallyLockTake(&TigerTallyLockEcu);
            //更新调度频率已缩短升级时间

            funcStep = THIRD_STEP2;
            LOG_DBG(" --check tiger tally back,state ok\r\n");
#elif UPGRADE_ECU
            
            LOG_DBG(" --check tiger tally back,state ok:%d\r\n",TimeSlice_GetSliceTime());
            TigerTallyLockTake(&TigerTallyLockEcu);
            TigerTallyLockBack(&TigerTallyLockEcu,TALLY_RETURN_SUCCESS,NULL,0);
            funcStep = THIRD_STEP2;
#else
            funcStep = THIRD_STEP0;
#endif
            break;
        case TALLY_RETURN_ERROR:
            memset(answerDescription,0x00,sizeof(resoutDescription));
            strcpy((char*)(answerDescription),"answer_download");
            memset(resoutDescription,0x00,sizeof(resoutDescription));
            strcpy((char*)(resoutDescription),(const char*)(TigerTallyLockEcu.returnMsg));
            funcStep = THIRD_STEP_ERROR;
        break;
        default:
            funcStep = THIRD_STEP1;
            break;
        }  
    break;
    case THIRD_STEP2:
        //TODO:文件验签
        switch (TigerTallyLockCheck(&TigerTallyLockEcu))
        {
        case TALLY_RETURN_SUCCESS:
            if(AT_state == AT_IDLE){
#if UPGRADE_ECU
                OtaCmdMsgAckPkgInit(&otaMsgAckPkg);
                OtaServerMsgAck(1,RTE_GEN_OTA_CMD_ACK_ID,true,otaCmdMsgPkg.data.taskId,"ota_up","answer_fcheck","ok");
                //检测如果校验没问题则开始升级任务
                if (0x01 == ThirdHasBeenCreat(VehicleOtaEcuUpGradeMainLoop))
                    CreatThird("OtaUg",To_OS_Slice_Time(20,OS_MSEC),10,VehicleOtaEcuUpGradeMainLoop);
                //交虎符-开始文件升级
                TigerTallyLockTake(&TigerTallyLockEcu);
                LOG_DBG(" --file tiger tally back,state ok\r\n");
                funcStep = THIRD_STEP3;
#else
                LOG_DBG("file update ok return\r\n");
                TimeSlice_SetSliceTime(SLICE_DEFUT_TIME);  
                funcStep = THIRD_STEP0;
#endif
            }else{
                printf("fcheck complete but AT NOT IDLE...\r\n");
            }
            break;
        case TALLY_RETURN_ERROR:
            memset(answerDescription,0x00,sizeof(resoutDescription));
            strcpy((char*)(answerDescription),"answer_dowload");
            memset(resoutDescription,0x00,sizeof(resoutDescription));
            strcpy((char*)(resoutDescription),(const char*)(TigerTallyLockEcu.returnMsg));
            funcStep = THIRD_STEP_ERROR;
            break;
        default:
            //funcStep = THIRD_STEP1;
            break;
        }  
    break;
    case THIRD_STEP3:
        switch (TigerTallyLockCheck(&TigerTallyLockEcu))
        {
        case TALLY_RETURN_SUCCESS:
            //文件下载升级成功开始新一轮ECU升级
            LOG_DBG("--ecu upgrade completed,next one\r\n");
            // TimeSlice_SetSliceTime(SLICE_DEFUT_TIME); need to be uncomment
            funcStep = THIRD_STEP0;
            break;
        case TALLY_RETURN_ERROR:
            OtaUpgradeEndHandle(FALSE);
            memset(answerDescription,0x00,sizeof(resoutDescription));
            strcpy((char*)(answerDescription),"answer_upgrade");
            memset(resoutDescription,0x00,sizeof(resoutDescription));
            strcpy((char*)(resoutDescription),"upErr");
            funcStep = THIRD_STEP_ERROR;
        break;
        default:
            funcStep = THIRD_STEP3;
            break;
        }
    break;
    case THIRD_STEP_ERROR:
            if(AT_state == AT_IDLE){
                OtaCmdMsgAckPkgInit(&otaMsgAckPkg);
                LOG_DBG("Process the results:%s-%s\r\n",answerDescription,resoutDescription);
                OtaServerMsgAck(1,RTE_GEN_OTA_STATE_ACK_ID,false,otaCmdMsgPkg.data.taskId,"ota_up",answerDescription,resoutDescription);
                memset(resoutDescription,0x00,sizeof(resoutDescription));
                memset(answerDescription,0x00,sizeof(resoutDescription));
                // TimeSlice_SetSliceTime(SLICE_DEFUT_TIME);  need to be uncomment
                funcStep = THIRD_STEP0;
                // chackTimes = 0;
                curdownTimes = 0;
                OTA_OutOTAUpgradeMode();
                TaskToClosed(thisTask);
            }else{
                printf("VehicleEcuQueueOTAMainLoop-thirdStep error but AT NOT IDLE ..\r\n");
            }
    break;

    }
}

static update_app_type APP_TYPE = UPDATE_TYPE_NONE;
static char tAppFileName[20]  = {0};
//文件下载任务
void VehicleOtaStateFileDownloadMainLoop(void){
    static uint8_t funcStep=0;
    // static uint8_t chackTimes=0;
    // static uint8_t fileType;
    static uint8_t answerDescription[MAX_RETURN_MSG] = {0};
    uint8_t *downloadFileName;
    uint8_t fileIndex = NO_FILE;
    // uint8_t count2strBuf[8];
    tTaskItem *thisTask;
    thisTask = FindRunnningItem();
    switch (funcStep)
    {
    case THIRD_STEP0:
        LOG_DBG("--in VehicleOtaStateFileDownloadMainLoop\r\n");
        CloseInterupt_CAN();
        //TODO:检查目标升级ECU,获得相关参数
        OtaStateManage.step_ecu_files = 0;
        OtaStateManage.step_files = 0;
        InintTigerTallyLock(&TigerTallyLockDownload);
#if OTA_IGNORE_DWL
#else
        if(NO_FILE != (fileIndex = CheckFileName(otafileName[0])))DeleteFile(fileIndex);
        if(NO_FILE != (fileIndex = CheckFileName(otafileName[1])))DeleteFile(fileIndex);
        if(NO_FILE != (fileIndex = CheckFileName(otafileName[2])))DeleteFile(fileIndex);
#endif

        APP_TYPE = Boot_IsAppType(TBOX_CUR_TYPE_ADDR);
        if(APP_TYPE == UPDATE_TYPE_A){
            memset(tAppFileName, 0x00, sizeof(tAppFileName));
            strcpy(tAppFileName,"Tapp_B");
        }else if(APP_TYPE == UPDATE_TYPE_B){
            memset(tAppFileName, 0x00, sizeof(tAppFileName));
            strcpy(tAppFileName,"Tapp_A");
        }else{
            // 如果既不是A面也不是B面，则认为当前是A面
            strcpy(tAppFileName,"Tapp_B");
            printf("VehicleOtaStateFileDownloadMainLoop-UPDATE_TYPE_NONE...\r\n");
        }

        if(NO_FILE != (fileIndex = CheckFileName((uint8_t *)tAppFileName)))DeleteFile(fileIndex);

        SaveFileAll();
        RecoverBlock();

        //检查目标ECU的升级文件是否匹配
        printf("filetype=%d\r\n",OtaStateManage.OtaEcuData.fileData[OTA_OTA_FILE].fileType);
        printf("ecutype=%d\r\n",OtaStateManage.ecuType);
        if(!OtaIsMappingFile(OtaStateManage.ecuType,OtaStateManage.OtaEcuData.fileData[OTA_OTA_FILE].fileType)){
            printf("--ota file type not mapping ecu type, %d, %d\r\n", OtaStateManage.ecuType, OtaStateManage.OtaEcuData.fileData[OTA_OTA_FILE].fileType);
            strcpy((char*)(answerDescription),"notMapping");

            funcStep = THIRD_STEP_ERROR;

        }else{
            funcStep = THIRD_STEP1;
        }
    break;
    case THIRD_STEP1:
        switch (TigerTallyLockCheck(&TigerTallyLockDownload))
        {
        case TALLY_OK:  
            if(AT_state == AT_IDLE){
                LOG_OTA("--TALLY_OK OtaStateManage.step_ecu_files:%d-fatherLinkLen:%d\r\n",OtaStateManage.step_ecu_files,OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].fatherLinkLen);
                LOG_OTA("--OtaStateManage.step_files:%d,sliceFileCount:%d\r\n",OtaStateManage.step_files,OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].sliceFileCount);
                LOG_OTA("--countdownFiles:%d,file index:%d",OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].countdownFiles,OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].fileIndex);

                if(( OtaStateManage.step_files+1 > OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].sliceFileCount)||(0 == OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].sliceFileCount)){
                    // OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].downloadEcuFileSizeSum = 0;
                    OtaStateManage.step_files = 0;                
                    OtaStateManage.step_ecu_files++;
                    if(OtaStateManage.step_ecu_files > OTA_OTA_FILE){
                        TigerTallyLockBack(&TigerTallyLockEcu,TALLY_RETURN_SUCCESS,NULL,0);
                        OtaCmdMsgAckPkgInit(&otaMsgAckPkg);
                        OtaServerMsgAck(1,RTE_GEN_OTA_CMD_ACK_ID,true,otaCmdMsgPkg.data.taskId,"ota_up","answer_download","ok");
                        OpenInterupt_CAN();
                        funcStep = THIRD_STEP0;
                        TaskToClosed(thisTask);
                        return;
                    }
                }

                funcStep = THIRD_STEP2;
            }else{
                printf("VehicleOtaStateFileDownloadMainLoop-thirdStep1 but AT NOT IDLE...\r\n");
            }
            break;
        case TALLY_RETURN_SUCCESS:
            //文件下载升级成功
            LOG_DBG("--this step file download ok next one\r\n");
            OtaStateManage.step_files++;
            OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].countdownFiles--;
            //TODO:检查下载总文件大小是否与实际大小一致
            LOG_DBG("--OtaStateManage.downloadFileState[%d].downloadEcuFileSizeSum:%d,targetFileLen:%d\r\n",OtaStateManage.step_ecu_files,OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].downloadEcuFileSizeSum, OtaStateManage.otaDownloadFileParam.targetFileLen);
            if(OtaStateManage.step_files+1 > OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].sliceFileCount){
                if(OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].downloadEcuFileSizeSum == OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].fileSizeSum){ 
                    LOG_DBG("--download file ok,check file len complete\r\n");
                    OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].fileState = TRUE;
                    //OtaFileDownTest();
                }else{
                    //文件长度不一致，下载出现问题,删除文件
                    LOG_DBG("--download file error,check file target != current\r\n");
                    OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].downloadEcuFileSizeSum = 0;
                    OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].fileIndex = 0xff;
                    OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].fileState = FALSE;
                }
            }
            InintTigerTallyLock(&TigerTallyLockDownload);
            //开始新一轮文件下载
            break;
        case TALLY_RETURN_ERROR:
            LOG_DBG("--ecu files downloads error,delete file index:%d\r\n",OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].fileIndex);
            DeleteFile(OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].fileIndex);
            TigerTallyLockBack(&TigerTallyLockEcu,TALLY_RETURN_ERROR,"downErr",strlen("downErr"));
            OpenInterupt_CAN();
            funcStep = THIRD_STEP0;
            TaskToClosed(thisTask);
            break;
        default:
            break;
        }
    break;
    case THIRD_STEP2:
        //TODO：检查是否存在该文件下载需求
        if(0 == OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].fileSizeSum){
            LOG_DBG("--no need download this file\r\n");
            funcStep = THIRD_STEP1;
        }else{
            if(OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].sliceFileCount > FILE_ADDR_ITEM_MAX){
                LOG_DBG("--error: ota file slice > max count\r\n");
                strcpy((char*)(answerDescription),"sliceOut");
                funcStep = THIRD_STEP_ERROR;
                return;
            }
            //检查是否已经创建相关文件
            if(OTA_TBOX == OtaStateManage.ecuType && OTA_OTA_FILE == OtaStateManage.step_ecu_files){
                memset(otafileName[2],0x00,sizeof(otafileName[2]));
                strcpy((char*)(otafileName[2]), tAppFileName);

            }
            LOG_DBG("--check file:%s\r\n",otafileName[ OtaStateManage.step_ecu_files]);
            fileIndex = CheckFileName(otafileName[ OtaStateManage.step_ecu_files]);

#if OTA_IGNORE_DWL
#else
            if(NO_FILE == fileIndex){
                fileIndex = CreatFileHandle(otafileName[ OtaStateManage.step_ecu_files],0);
#endif
                LOG_DBG("--no this file creat\r\n");
                //没有则创建文件
                if(fileIndex < FILES_MAX){
                    //文件创建成功
                    OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].fileIndex = fileIndex;
                    LOG_DBG("--fileIndex:%d",OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].fileIndex);
                }else{
                    //文件创建失败
                    LOG_DBG("--creat file error\r\n");
                }
#if OTA_IGNORE_DWL
#else
            }
#endif

            LOG_OTA("--file index:%d,file name:%s\n",fileIndex,otafileName[OtaStateManage.step_ecu_files]);

            if(OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].fatherLinkLen > FURL_LEN_MAX){
                LOG_DBG("--url len out of range\r\n");
                funcStep = THIRD_STEP1;
                break;
            }
            LOG_DBG("--OtaStateManage.step_ecu_files:%d-fatherLinkLen:%d\r\n",OtaStateManage.step_ecu_files,OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].fatherLinkLen);
            //初始化下载连接参数
            memset(OtaStateManage.otaDownloadFileParam.fileUrl,0x00,OTA_DOWNLOAD_FILE_URL_MAX_LEN);
            memset(OtaStateManage.otaDownloadFileParam.fileName,0x00,DEVICE_NAME_LEN_MAX);
            OtaStateManage.otaDownloadFileParam.downloadedLen = 0;
            OtaStateManage.otaDownloadFileParam.downloadState = FILE_NONE;
            OtaStateManage.otaDownloadFileParam.targetFileLen = 0;
            OtaStateManage.otaDownloadFileParam.urlLen = 0;
            //制作下载链接参数
            memcpy(OtaStateManage.otaDownloadFileParam.fileUrl,OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].fatherUrl ,OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].fatherLinkLen);
            strcat(OtaStateManage.otaDownloadFileParam.fileUrl,OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].Addr[OtaStateManage.step_files].sunUrl);
            LOG_DBG("--creat download url:%s",OtaStateManage.otaDownloadFileParam.fileUrl);
            //设置下载状态为请求下载
            OtaStateManage.otaDownloadFileParam.downloadState = FILE_REQUEST;
            OtaStateManage.otaDownloadFileParam.targetFileLen = OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].Addr[OtaStateManage.step_files].fileSize;
            LOG_DBG("--get targetFileLen[step_ecu_files:%d]-[step_files:%d]:%d\r\n",OtaStateManage.step_ecu_files,OtaStateManage.step_files,OtaStateManage.otaDownloadFileParam.targetFileLen);
            downloadFileName = otafileName[OtaStateManage.step_ecu_files];
            if(strlen((const char*)downloadFileName)>DEVICE_NAME_LEN_MAX){
                //TODO:error文件名超长
            }else{
                memcpy(OtaStateManage.otaDownloadFileParam.fileName,downloadFileName,strlen((const char*)downloadFileName));
                OtaStateManage.otaDownloadFileParam.fileIndex = fileIndex;
            }
            //交控制权

            TigerTallyLockTake(&TigerTallyLockDownload);
            if (0x01 == ThirdHasBeenCreat(DownloadEcuFile))
                CreatThird("lodFile",To_OS_Slice_Time(100,OS_MSEC),10,DownloadEcuFile); 

            funcStep = THIRD_STEP1;
        }
        break;
        case THIRD_STEP_ERROR:
            TigerTallyLockBack(&TigerTallyLockEcu,TALLY_RETURN_ERROR,answerDescription,strlen((const char*)answerDescription));
            OpenInterupt_CAN();
            funcStep = THIRD_STEP0;
            TaskToClosed(thisTask);
        break;
    }
}

//用于文件校验的主任务
void VehicleOtaStateFileCheckMainLoop(void){
    static uint8_t funcStep = 0;

    // printf("VehicleOtaStateFileCheckMainLoop-funcStep:%d\r\n", funcStep);

    // static uint8_t chackTimes = 0;
    static uint16_t readTimes = 0,readEndSize = 0; //根据总长度读取次数和余数
    static uint32_t currentBaseAddr = 0xffffffff;
    static uint8_t baseAddrCount = 0;
    // uint8_t fileIndex = 0xff;
    static uint32_t fileSize = 0;
    uint8_t readBuff[512];
    uint32_t readLen = 0,needReadLen = 0;
    static tFileHead fileHead;	
    uint16_t i = 0;
    uint8_t md5Data[16] = {0};
    char md5String[64] = {0};
    char temp[4] = {0};
    int8_t ret;
    tTaskItem *thisTask;
    static uint8_t hexBinIndex = 0;
    static uint32_t hexBaseAddr = 0;
    static uint32_t hexLastAddr = 0;

    str_S19LineData S19LineData;
    str_HEXLineData HEXLineData;
    thisTask = FindRunnningItem();
    switch (funcStep)
    {
    case THIRD_STEP0:
        LOG_DBG("--creat check file mainloop\r\n");
        CloseInterupt_CAN();
        currentBaseAddr = 0xffffffff;
        readTimes = 0;
        readEndSize = 0;
        // fileIndex = 0xff;
        fileSize = 0;
        baseAddrCount = 0;
        OtaStateManage.step_ecu_files = 0;
        hexBinIndex = 0;
        hexBaseAddr = 0;
        hexLastAddr = 0;
        OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.hasBinSize = 0;
        OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.BinHeadAddr = 0;
        memset(OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].hexBinMsg,0x00,sizeof(OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].hexBinMsg));
        OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].checkState = FALSE;
        funcStep = THIRD_STEP1;
    break;
    case THIRD_STEP1:
        if(0 == OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].fileSizeSum){
            LOG_DBG("--check file:no this file\r\n");
            OtaStateManage.step_ecu_files++;
        }else{ 
            MD5Init(&md5Handle);
            //获得MD5数据，文件长度等信息，打开文件
            printf("check file index:%d\r\n", OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].fileIndex);
            fileHead = OpenFile(OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].fileIndex);
            //获得需求读取的次数
            readTimes = OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].downloadEcuFileSizeSum / sizeof(readBuff);
            readEndSize = OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].downloadEcuFileSizeSum % sizeof(readBuff);
            //设置偏移从头开始
            SetFileOffset(&fileHead,0,0);
            LOG_DBG("--md5 check begin,readTimes:%d,readEndSize:%d\r\n",readTimes,readEndSize);
            funcStep = THIRD_STEP2;
        }
        if(OtaStateManage.step_ecu_files > OTA_OTA_FILE){
            LOG_DBG("--check file:file check complete\r\n");
            TigerTallyLockBack(&TigerTallyLockEcu,TALLY_RETURN_SUCCESS,NULL,0);
            OpenInterupt_CAN();
            funcStep = THIRD_STEP0;
            TaskToClosed(thisTask);
            return;
        }
    break;
    case THIRD_STEP2:
        switch (OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].fileType)
        {
        case OTA_FILE_BIN:
            // if (readTimes) needReadLen = sizeof(readBuff);
            // else needReadLen = readEndSize;
            readTimes?(needReadLen = sizeof(readBuff)):(needReadLen = readEndSize);
            readTimes --;
            //以512位数据为一组进行处理
            readLen = ReadFromFile(&fileHead,readBuff,needReadLen);
            OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.hasBinSize += readLen;
            break;
        case OTA_FILE_AFF:
            // if (readTimes) needReadLen = sizeof(readBuff);
            // else needReadLen = readEndSize;
            readTimes?(needReadLen = sizeof(readBuff)):(needReadLen = readEndSize);
            readTimes --;
            //以512位数据为一组进行处理
            readLen = ReadFromFile(&fileHead,readBuff,needReadLen);
            OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.hasBinSize += readLen;
            break;
        case OTA_FILE_S19:     
            memset(readBuff,0x00,sizeof(readBuff));
            readLen = ReadFromTextOneLine(&fileHead,readBuff,sizeof(readBuff));

            printf("check s19...readLen:%d, fileSizeSum:%d\r\n", readLen, OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].downloadEcuFileSizeSum);

            //LOG_DBG("get lens-%d:%s",readLen,readBuff);
            //LOG_DBG("%s",readBuff);
            ret = validateS19String((char *)readBuff,readLen,&S19LineData);
            if(S19_NO_ERROR == ret){
                if(S19_TYPE_S1 == S19LineData.Type || S19_TYPE_S2 == S19LineData.Type || S19_TYPE_S3 == S19LineData.Type)
                    OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.hasBinSize += S19LineData.dataLen;
                //TODO：增加首地址获取
                if(OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.BinHeadAddr == 0 || OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.BinHeadAddr > S19LineData.address) 
                    OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.BinHeadAddr = S19LineData.address;
            }else{
                LOG_DBG("--check s19 error:%d\r\n",ret);
                LOG_DBG("--data:%s\r\n",readBuff);
            }
            break;
        case OTA_FILE_HEX:
            readLen = ReadFromTextOneLine(&fileHead,readBuff,sizeof(readBuff));
            LOG_DBG("--get-%d:%s\r\n",readLen,readBuff);
            ret = validateHEXString((char *)readBuff,readLen,&HEXLineData);
            if(HEX_NO_ERROR == ret){
                if(HEX_ELA == HEXLineData.Type){
                    hexBaseAddr = HEXLineData.baseAddr<<16;
                    hexLastAddr = hexBaseAddr;
                    LOG_OTA("--get new base addr:%x\r\n",hexBaseAddr);
                }
                if(HEX_DATA == HEXLineData.Type){
                    //请勿去除此注释：此次为了避开index 0 所以不为hexLastAddr给赋值基地址，这样数组index0的长度为0，而将第一段数据直接赋值给iindex 1，这是特意设计
                    if((hexLastAddr)!=( HEXLineData.address + hexBaseAddr)){
                        LOG_OTA("--last one file len:0x%x\r\n",OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].hexBinMsg[hexBinIndex].hasBinSize);
                        LOG_OTA("--last:%x,now:%x",hexLastAddr + HEXLineData.dataLen,hexBaseAddr + HEXLineData.address);
                        if(hexBinIndex < MAX_BASE_CONUT)hexBinIndex++;  //hexBinIndex 从1开始计数
                        OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].hexBinMsg[hexBinIndex].BinHeadAddr = hexBaseAddr + HEXLineData.address;
                        LOG_OTA("binheadaddr:%x",OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].hexBinMsg[hexBinIndex].BinHeadAddr);
                    }
                    hexLastAddr = hexBaseAddr + HEXLineData.address + HEXLineData.dataLen;
                    OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].hexBinMsg[hexBinIndex].hasBinSize += HEXLineData.dataLen;
                    LOG_OTA("--data:%x\r\n",OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].hexBinMsg[hexBinIndex].hasBinSize);
                    if(currentBaseAddr != HEXLineData.baseAddr){
                        currentBaseAddr = HEXLineData.baseAddr;
                        if(baseAddrCount < MAX_BASE_CONUT-1) baseAddrCount++;
                        else LOG_DBG("--out of hex base:%d\r\n",baseAddrCount);
                    }
                }
            }else{
                LOG_DBG("--check hex error:%d\r\n",ret);
                LOG_DBG("--data:%s\r\n",readBuff);
            }
            break;        
        default:
            LOG_DBG("--unknow file type error\r\n");
            funcStep = THIRD_STEP3;
            break;
        }
        //LOG_DBG("--check file:read file[%d-%d]:\r\n",fileSize,readLen,readBuff);
        fileSize += readLen;
        printf("check s19...fileSize:%d\r\n", fileSize);
        if(-1 == (int16_t)readLen){
            //文件错误，报错
            LOG_DBG("--get file error\r\n");
            funcStep = THIRD_STEP3;
        }
        if(0 == readLen){
            LOG_DBG("--get file end\r\n");
            //文件读取完毕
            funcStep = THIRD_STEP3;
        }
        
        MD5Update(&md5Handle,(unsigned char*)readBuff,readLen);
        if(fileSize == OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].downloadEcuFileSizeSum){
            //接收完成
            funcStep = THIRD_STEP3;
        }else if(fileSize > OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].downloadEcuFileSizeSum){
            //接收异常
            funcStep = THIRD_STEP_ERROR;
        }

#if OTA_IGNORE_MD5
        funcStep = THIRD_STEP3;
#endif

    break;
    case THIRD_STEP3:
        //处理结尾位置数据
        printf("check s19-third step3...\r\n");
        MD5Final(md5Data,&md5Handle);
        strcpy((char*)(md5String),"");
        for (i = 0; i < 16; i++)
        {   
            sprintf(temp,"%02x",md5Data[i]);
            strcat(md5String,temp);
            //LOG_DBG("--file MD5:%x\r\n",md5Data[i]);
        }

#if OTA_IGNORE_MD5
        // VCU sv=1
        // OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].hexBinMsg[1].BinHeadAddr = 0x500200;
        // OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].hexBinMsg[1].hasBinSize = 0x46828;

        // VCU sv=1.2
        // OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.BinHeadAddr = 0x500200;
        // OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.hasBinSize = 290140;
        // OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].hexBinMsg[1].BinHeadAddr = 0x500200;
        // OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].hexBinMsg[1].hasBinSize = 290140;

        // BMS AC08
        if(OtaStateManage.step_ecu_files == 1){
            OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.BinHeadAddr = 0x1ffff000;
            OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.hasBinSize =  1264;
        }else if(OtaStateManage.step_ecu_files == 2){
            OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.BinHeadAddr = 0x10000;
            OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.hasBinSize =  222892;
        }

#endif


        printf("--get bin counts:%x-%d\r\n",OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.BinHeadAddr,OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].binMsg.hasBinSize);
        for(int i=0;i<MAX_BASE_CONUT;++i){
            LOG_OTA("--base %d:%x-0x%x\r\n", i, OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].hexBinMsg[i].BinHeadAddr,OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].hexBinMsg[i].hasBinSize);
        }
        LOG_OTA("--        source MD5:%s\r\n",OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].md5Code);
        LOG_DBG("--calculate file MD5:%s\r\n",md5String);


#if OTA_IGNORE_MD5
#else
        if(!OTA_Md5CodeCheck((uint8_t *)md5String, OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].md5Code,16)){
#endif

            LOG_OTA("--calculate file MD5 OK\r\n");
            OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].checkState = TRUE;
            //文件校验完成,继续下一个文件
            OtaStateManage.step_ecu_files++;
            //初始化相关参数，必须
            readTimes = 0;
            readEndSize = 0;
            fileSize = 0;
            // chackTimes = 0;
            funcStep = THIRD_STEP1;

#if OTA_IGNORE_MD5
#else
        }else{
            OtaStateManage.step_ecu_files++; //测试用，需要删除
            LOG_DBG("--calculate file MD5 ERR,next one\r\n");
            LOG_DBG("--        source MD5:%s\r\n",OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].md5Code);
            LOG_DBG("--calculate file MD5:%s\r\n",md5String);
            funcStep = THIRD_STEP_ERROR;
            return;
        }
#endif
    break;
    case THIRD_STEP_ERROR:
            LOG_DBG("--file check err\r\n");
            //文件校验失败直接返回异常
            TigerTallyLockBack(&TigerTallyLockEcu,TALLY_RETURN_ERROR,"md5Err",strlen("md5Err"));
            readTimes = 0;
            readEndSize = 0;
            fileSize = 0;
            // chackTimes = 0;
            OpenInterupt_CAN();
            funcStep = THIRD_STEP0;
            TaskToClosed(thisTask);
    break;
    default:
    break;
    }
}

//TODO:用于升级的主任务
void VehicleOtaEcuUpGradeMainLoop(void){
    static uint8_t funcStep = 0;
    // static uint8_t chackTimes = 0;
    // uint8_t threadState = 0;
    tTaskItem *thisTask;
    // uint8_t bmsType=0;
    uint8_t retMsg[32] = {0};
    uint16_t i=0;
    bool findEcuDevice = FALSE;
    uint8_t fileIndex = 0xff;

    thisTask = FindRunnningItem();

    switch (funcStep)
    {
    case THIRD_STEP0:
        LOG_DBG("--ecu upgrade begin\r\n");
        for (i = 0; i < ECU_DEVICE_ID_LIST_COUNT; i++)
        {
            //LOG_DBG("--ecuType-%d:%d,%d\r\n",i,OtaStateManage.ecuType,ecuDeviceIdList[i].ecuType);
            //LOG_DBG("--deviceId-%s,%s\r\n",OtaStateManage.OtaEcuData.OtaParam.deviceId,ecuDeviceIdList[i].deviceIdStr);
            if(OtaStateManage.ecuType == ecuDeviceIdList[i].ecuType && (!strcmp(OtaStateManage.OtaEcuData.OtaParam.deviceId,ecuDeviceIdList[i].deviceIdStr))){
                findEcuDevice = TRUE;
                break;
            }
        }
        if(!findEcuDevice || (ECU_DEVICE_ID_LIST_COUNT == i)){
            LOG_DBG("--unknow type ecu upgrade false:\r\n");
            memset(retMsg,0x00,sizeof(retMsg));
            strcpy((char*)retMsg,"unknEcu");
            funcStep = THIRD_STEP_ERROR;  
            break;
        }
        LOG_DBG("--get device id in list:%d-id:%s\r\n",i,ecuDeviceIdList[i].deviceIdStr);
        switch (OtaStateManage.ecuType)
        {
        case OTA_BMS:
            OtaStateManage.upGradeFunc = ecuDeviceIdList[i].upGradeFunc;
            funcStep = THIRD_STEP1;
            break;
        case OTA_MCU:
            OtaStateManage.upGradeFunc = ecuDeviceIdList[i].upGradeFunc;
            funcStep = THIRD_STEP1;
            break;
        case OTA_TBOX:
            //修改OTA文件名为老boot能识别的文件名
            printf("VehicleOtaEcuUpGradeMainLoop-case OTA_TBOX...\r\n");
            fileIndex = CheckFileName(otafileName[2]);
            if(NO_FILE != fileIndex){
                ChangeFileName(fileIndex, (uint8_t *)tAppFileName,strlen(tAppFileName));
            }
            TigerTallyLockBack(&TigerTallyLockEcu,TALLY_RETURN_SUCCESS,NULL,0);
            // SetUpgradeMark(UPGRADE_OTA);
            // SetSysRunState(SYS_RESTART);
            funcStep = THIRD_STEP0;
            if(thisTask)
                TaskToClosed(thisTask);
            break;
        case OTA_VCU:
           // memset(retMsg,0x00,sizeof(retMsg));
            // strcpy(retMsg,"noVCU");
            // funcStep = THIRD_STEP_ERROR;
            OtaStateManage.upGradeFunc = ecuDeviceIdList[i].upGradeFunc;
            funcStep = THIRD_STEP1;
            break; 
         case OTA_BCM:
            OtaStateManage.upGradeFunc = ecuDeviceIdList[i].upGradeFunc;
            funcStep = THIRD_STEP1;
            break;
        case OTA_OBC:
            OtaStateManage.upGradeFunc = ecuDeviceIdList[i].upGradeFunc;
            funcStep = THIRD_STEP1;
            break;     
        default:
            LOG_DBG("--unknow ecu type end\r\n");
            memset(retMsg,0x00,sizeof(retMsg));
            strcpy((char*)retMsg,"unknECU");
            funcStep = THIRD_STEP_ERROR;
            break;
        }
    break;
    case THIRD_STEP1:

#if OTA_IGNORE_UPGRADE
        TigerTallyLockEcu.state = TALLY_RETURN_SUCCESS;
#else
        OtaStateManage.upGradeFunc(); //执行诊断升级任务
#endif

        if(TALLY_OUT != TigerTallyLockCheck(&TigerTallyLockEcu)){
            LOG_DBG("--local upgrade end\r\n");
            // chackTimes = 0;
            funcStep = THIRD_STEP0;
            if(thisTask)
                TaskToClosed(thisTask);
        }
    break;
    case THIRD_STEP_ERROR:
        // chackTimes = 0;
        funcStep = THIRD_STEP0;
        TigerTallyLockBack(&TigerTallyLockEcu,TALLY_RETURN_ERROR,retMsg,strlen((const char*)(retMsg)));
        if(thisTask)
            TaskToClosed(thisTask);
    break;
    }
}


//用于升级命令接收，完成和超时状态返回任务 1s一次
void VehicleOtaCmdAckMain(void){
    // static uint8_t funcStep = 0;
    // static uint8_t chackTimes = 0;
    uint8_t threadState = 0;
    tTaskItem *thisTask;

    thisTask = FindRunnningItem();
    LOG_DBG("--in VehicleOtaCmdAckMain times:%d\r\n",otaMsgMark.ticksSec);
    //循环计数，如果到时间则检测判断是否相等，来判断返回什么结果
    otaMsgMark.ticksSec++;
    if(otaMsgMark.ticksSec>OTA_MSG_ACK_MAX_TIME){
        LOG_DBG("--ticksSec>OTA_MSG_ACK_MAX_TIME,task closed\r\n");
        if((otaMsgMark.ecuMsgReciveCount > otaMsgMark.ecuCount) || (otaMsgMark.ecuCount == 0)){
            //返回异常接收，清除数据
            OtaMsgMarkDataInit(&otaMsgMark);
            LOG_DBG("--otaMsgMark.ecuMsgReciveCount:%d > otaMsgMark.ecuCount:%d ota filed\r\n",otaMsgMark.ecuMsgReciveCount,otaMsgMark.ecuCount);
        }

        // funcStep = THIRD_STEP0;
        TaskToClosed(thisTask);
    }
    if((otaMsgMark.ecuMsgReciveCount == otaMsgMark.ecuCount) && (otaMsgMark.ecuCount != 0)){
        //接收完成，返回正常，开启升级任务
        LOG_DBG("--otaMsgMark.ecuMsgReciveCount:%d == otaMsgMark.ecuCount:%d ota begin\r\n",otaMsgMark.ecuMsgReciveCount,otaMsgMark.ecuCount);
        threadState = ThirdHasBeenCreat(VehicleOtaStateCheckMainLoop);
        if (threadState == 0x01){
            CreatThird("OtaMsgCk",To_OS_Slice_Time(100,OS_MSEC),10,VehicleOtaStateCheckMainLoop);
        }
        LOG_DBG("--get data count right,task closed\r\n");
        //结束任务
        // funcStep = THIRD_STEP0;
        TaskToClosed(thisTask);
    }
} 


//下载OTA数据到目标文件任务函数
//输入：void
//返回: void
extern int Wireless_Receive_BackBuff; 
void DownloadEcuFile(void){
#if OTA_IGNORE_DWL
    static uint8_t funcStep = 13;
#else
    static uint8_t funcStep = 0;
#endif
    printf("DownloadEcuFile-funcStep:%d, AT_state:%d\r\n", funcStep, AT_state);

    // static uint8_t chackTimes = 0;
    static uint8_t chackTimes_storefile = 0;
    static uint8_t chackTimes_httpget = 0;
    static uint8_t chackTimes_openfile = 0;
    static uint8_t chackTimes_readfile = 0;
    // static uint8_t getData0ErrorTimes = 0;
    // static uint16_t transfer_times=0;
    static uint32_t getDataLengthSum = 0;
    static uint8_t chackTimes_seekfile = 0;
    static const uint32_t fileIndex4G = 1027;   // 4G模块文件系统默认起始文件句柄
    // uint8_t binData[2048];
    // uint32_t downloadLength = 1024,getDataLength = 0;

    tTaskItem *thisTask;
    // uint32_t reciveFileSize = 0;
    uint8_t fileIndex = 0;
    tFileHead fileHead;	
    char httpConfigCmd[64];

    thisTask = FindRunnningItem();

    switch (funcStep)
    {
    case THIRD_STEP0:
        if(AT_state == AT_IDLE){
            FILE_CLOSE_CMD(fileIndex4G);  // 上次ota可能4g模块中没有关闭文件，先关文件
            funcStep = THIRD_STEP1;
            GOToSleep(TASK_AT_WAIT);
        }
        break;
    case THIRD_STEP1:
        if(OtaStateManage.otaDownloadFileParam.downloadState == FILE_REQUEST){
            //默认已经进入升级模式，及屏蔽CAN，GPS等信息
            //设置不上报信息头
            memset(httpConfigCmd,0x00,sizeof(httpConfigCmd));
            strcat(httpConfigCmd,"AT+ZHTTPCFG=responseheader,0\r\n");
            // USART2_SendMore(httpConfigCmd,strlen(httpConfigCmd));
	        // USART0_SendMore(httpConfigCmd,strlen(httpConfigCmd));
        }else{
            //没有请求直接退出任务
            funcStep = THIRD_STEP0;
            // chackTimes = 0;
            chackTimes_httpget = 0;
            // getData0ErrorTimes = 0;
            // transfer_times=0;
            getDataLengthSum = 0;
            TaskToClosed(thisTask);
            break;
        }
        if(AT_state == AT_IDLE){
            delay_ms(20);
            FILE_Delete_CMD((uint8_t *)OtaStateManage.otaDownloadFileParam.fileName,strlen((const char*)(OtaStateManage.otaDownloadFileParam.fileName)));
            GOToSleep(TASK_AT_WAIT);
            funcStep = THIRD_STEP2;
        }
        break;
    case THIRD_STEP2:
        if(AT_state == AT_IDLE){
            //设置Http请求
            LOG_DBG("send url:%s\n",OtaStateManage.otaDownloadFileParam.fileUrl);	
            HTTP_Link_CMD((uint8_t *)OtaStateManage.otaDownloadFileParam.fileUrl,strlen((const char*)(OtaStateManage.otaDownloadFileParam.fileUrl)));
            funcStep = THIRD_STEP3;
            GOToSleep(TASK_AT_WAIT);
        }
        break;
    case THIRD_STEP3:
		if (HTTP_link_cmd_ok){
            if(AT_state == AT_IDLE){
                //设置成功
                LOG_DBG("set url ok\n"); 
                //开始让4G模块自动下载数据
                HTTP_DataRequest_CMD();
                funcStep = THIRD_STEP4;
                GOToSleep(TASK_AT_WAIT);
            }
		}else{
			LOG_DBG("set url failed\n");
			funcStep = THIRD_STEP1;
			//通知服务器升级失败
		}
        break;
    case THIRD_STEP4:
		if (get4G_HTTP_DWL_CMPL() && AT_state == AT_IDLE){
            // 重置环形缓冲区
            clear_ringBuffer(getRingBuffer());
			LOG_DBG("http get ok\n");
			//用文件读取http get到的数据
			HTTP_StorageData_CMD((uint8_t *)OtaStateManage.otaDownloadFileParam.fileName,strlen((const char*)(OtaStateManage.otaDownloadFileParam.fileName)));
            GOToSleep(TASK_AT_WAIT);
			funcStep = THIRD_STEP5;
            chackTimes_httpget = 0;
			//下载文件
			//SysDelay(500);
			
		}else{
            if(AT_state != AT_IDLE){
                printf("ecuFileDownloadFail-THIRD_STEP4-AT_state:%d, current_at_cmd:%s\r\n", AT_state, getCurrentATCMD());
            }
            if (chackTimes_httpget > 10) {
                chackTimes_httpget = 0;
                funcStep = THIRD_STEP1;
            }
            chackTimes_httpget ++;
			LOG_DBG("http get fail\n");
			//通知服务器升级失败
		}        
        break;
    case THIRD_STEP5:
        if (getStore4GFileFlag() && AT_state == AT_IDLE){
            printf("DownloadEcuFile-store4Gfile succeed..\r\n");
            chackTimes_storefile = 0;
            FILE_Inquire_CMD((uint8_t *)OtaStateManage.otaDownloadFileParam.fileName,strlen((const char*)(OtaStateManage.otaDownloadFileParam.fileName)));
            funcStep = THIRD_STEP6;
            GOToSleep(TASK_AT_WAIT);
        }else{
            if(AT_state != AT_IDLE){
                printf("ecuFileDownloadFail-THIRD_STEP5-AT_state:%d, current_at_cmd:%s\r\n", AT_state, getCurrentATCMD());
            }
            chackTimes_storefile ++;
            if (chackTimes_storefile > 50) {
                chackTimes_storefile = 0;
                DeleteFile(fileIndex);
                OtaStateManage.otaDownloadFileParam.downloadState = FILE_ERROR;
                TigerTallyLockBack(&TigerTallyLockDownload,TALLY_RETURN_ERROR,"downErr",strlen("downErr"));
                printf("DownloadEcuFile-store4Gfile fail, end task..\r\n");
                TaskToClosed(thisTask);
                funcStep = THIRD_STEP0;
                break;
            }
            printf("DownloadEcuFile-store4Gfile fail, retry..\r\n");
        }
        break;
    case THIRD_STEP6:
		// reciveFileSize = checkFileSize(wireless_rxbuff,OtaStateManage.otaDownloadFileParam.fileName,strlen(OtaStateManage.otaDownloadFileParam.fileName));
		LOG_DBG("DownloadEcuFile-get recv len:%d,file len:%d\n",FILE_inquire_cmd_size,OtaStateManage.otaDownloadFileParam.targetFileLen);

		if(FILE_inquire_cmd_size == OtaStateManage.otaDownloadFileParam.targetFileLen){
			//文件接收完成，开始传输到外部flash
			LOG_DBG("check file name:%s\n",OtaStateManage.otaDownloadFileParam.fileName);
			fileIndex = CheckFileName((uint8_t *)OtaStateManage.otaDownloadFileParam.fileName);
            
			if(fileIndex == 0xff){
				LOG_DBG("no ota file creat\n");
				fileIndex = CreatFileHandle((uint8_t *)OtaStateManage.otaDownloadFileParam.fileName,0);
                OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].fileIndex = fileIndex;
			}
            LOG_DBG("in download file index:%d\n",fileIndex);
			LOG_DBG("file download complete\n");
			funcStep = THIRD_STEP7;
		}else{
			funcStep = THIRD_STEP5;
			//OTA_Request.fileSize = OTA_Request.reciveFileSize;
			SysDelay(100);
		}
        break;   

        case  THIRD_STEP7:
            if(AT_state == AT_IDLE){
                FILE_OPEN_CMD(OtaStateManage.otaDownloadFileParam.fileName, 0);
                GOToSleep(TASK_AT_WAIT);
                funcStep = THIRD_STEP8;
            }
            break;
        
        case  THIRD_STEP8:
            if (getOPEN_4G_FILE_HANDLE() > 0) {
                printf("DownloadEcuFile-open file succeed, handle:%d\r\n", getOPEN_4G_FILE_HANDLE());
                funcStep = THIRD_STEP9;
                break;
            }else{
                chackTimes_openfile++;
                if (chackTimes_openfile > 10 && AT_state == AT_IDLE) {
                    chackTimes_openfile = 0;
                    FILE_CLOSE_CMD(fileIndex4G);   // 很可能是文件已被打开导致的打不开(移远4G文件句柄默认1027)
                    printf("DownloadEcuFile-open file failed, end task..\r\n");
                    TaskToClosed(thisTask);
                    DeleteFile(fileIndex);
                    OtaStateManage.otaDownloadFileParam.downloadState = FILE_ERROR;
                    TigerTallyLockBack(&TigerTallyLockDownload,TALLY_RETURN_ERROR,"downErr",strlen("downErr"));
                    GOToSleep(TASK_AT_WAIT);
                    funcStep = THIRD_STEP7;
                }else if(AT_state != AT_IDLE){
                    printf("ecuFileDownloadFail-THIRD_STEP8-AT_state:%d, current_at_cmd:%s\r\n", AT_state, getCurrentATCMD());
                }
                printf("DownloadEcuFile-open file failed, retry...\r\n");
                break;
            }

        case  THIRD_STEP9:
            Wdg_Fade();
            if (getDataLengthSum == OtaStateManage.otaDownloadFileParam.targetFileLen) {
            // if (getDataLengthSum == 512) {

                printf("DownloadEcuFile-content size reached...\r\n");
                funcStep = THIRD_STEP12;
                break;
            }else{
                if(AT_state == AT_IDLE){
                    printf("DownloadEcuFile-content size not reached, getDataLengthSum:%d\r\n", getDataLengthSum);
                    FILE_SEEK_CMD(getOPEN_4G_FILE_HANDLE(), getDataLengthSum);
                    GOToSleep(TASK_OTA_DOWNLOAD_WAIT);
                    funcStep = THIRD_STEP10;
                }
                break;
            }
        case THIRD_STEP10: 
            Wdg_Fade();
            if (getSEEK_FLAG()) {
                if(AT_state == AT_IDLE){
                    chackTimes_seekfile = 0;
                    LOG_OTA("DownloadEcuFile-qfseek succeed...\r\n");
                    FILE_READ_CMD(getOPEN_4G_FILE_HANDLE(), OTA_TRANSFER_UNIT);
                    GOToSleep(TASK_OTA_DOWNLOAD_WAIT);
                    funcStep = THIRD_STEP11;
                }
            }else{
                chackTimes_seekfile ++;
                if(chackTimes_seekfile > 0){
                    chackTimes_seekfile = 0;
                    // LOG_OTA("DownloadEcuFile-qfseek failed...\r\n");
                    funcStep = THIRD_STEP9;
                }
            }
            break;

        case  THIRD_STEP11:
            Wdg_Fade();
            if (getReadLength() > 0) {
                chackTimes_readfile = 0;
                getDataLengthSum += getReadLength();
#if OTA_DEBUG_LOG
                printf("DownloadEcuFile-read file succeed, handle:%d, content:%s\r\n", getOPEN_4G_FILE_HANDLE(), getReadContent());
                char* pContent = getReadContent();
                printf("hex content:\r\n");
                for(int i=0;i<512;++i){
                    printf("%x ", pContent[i]);
                }
                printf("\r\nend\r\n");
#endif

                // 写到外部flash
                fileIndex = OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].fileIndex;
                LOG_OTA("downloadEcuFile-fileIndex:%d\r\n", fileIndex);
				fileHead = OpenFile(fileIndex);
                LOG_OTA("ota fileHead.writePtr:%d\r\n", fileHead.writePtr);
				WriteToFile_New(&fileHead,getReadContent(),getReadLength());
				CloseFile(fileIndex,&fileHead);
            }else{
                chackTimes_readfile++;
                if (chackTimes_readfile > 10) {
                    chackTimes_readfile = 0;
                    printf("DownloadEcuFile-read file failed, end task...\r\n");
                    TaskToClosed(thisTask);
                    DeleteFile(fileIndex);
                    OtaStateManage.otaDownloadFileParam.downloadState = FILE_ERROR;
                    TigerTallyLockBack(&TigerTallyLockDownload,TALLY_RETURN_ERROR,"downErr",strlen("downErr"));
                    getDataLengthSum = 0;
                    funcStep = THIRD_STEP0;
                    break;
                }
                printf("DownloadEcuFile-read file failed, retry...\r\n");
            }
            funcStep = THIRD_STEP9;
            break;

        case  THIRD_STEP12:
            Wdg_Fade();
            if(AT_state == AT_IDLE){
                FILE_CLOSE_CMD(fileIndex4G);  // 关闭4G缓存文件
                GOToSleep(TASK_AT_WAIT);
                funcStep = THIRD_STEP13;
            }
            break;
        case  THIRD_STEP13:
            Wdg_Fade();
            if(AT_state == AT_IDLE){
                OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].downloadEcuFileSizeSum += getDataLengthSum;
                LOG_DBG("move ota file complete\n");
                OtaStateManage.otaDownloadFileParam.downloadState = FILE_DLOADED;
                FILE_Delete_CMD((uint8_t *)OtaStateManage.otaDownloadFileParam.fileName,strlen((const char*)(OtaStateManage.otaDownloadFileParam.fileName)));
                //交回控制权
                if(0x02 == OtaStateManage.otaDownloadFileParam.errorCode)
                    TigerTallyLockBack(&TigerTallyLockDownload,TALLY_RETURN_ERROR,"downErr",strlen("downErr"));
                else TigerTallyLockBack(&TigerTallyLockDownload,TALLY_RETURN_SUCCESS,NULL,0);
                SaveFileAll();

#if OTA_IGNORE_DWL
                funcStep = THIRD_STEP13;
                OtaStateManage.downloadFileState[OtaStateManage.step_ecu_files].downloadEcuFileSizeSum = OtaStateManage.OtaEcuData.fileData[OtaStateManage.step_ecu_files].fileSizeSum;
#else
                funcStep = THIRD_STEP0;
#endif

    #if OTA_DEBUG_LOG
                int fileHandle = CheckFileName(tAppFileName);
                if (fileHandle != 0xff){
                    fileHead = OpenFile(fileHandle);
                    char buf[513] = {0};
                    printf("ybw_file_test-dataSize:%d\r\n", fileHead.dataSize);
                    printf("ybw_file_test-rd_buf:\r\n");
                    int rdPtrBack;
                    fileHead.readPtr = 0;
                    for (int i=0;i<=fileHead.dataSize/512;++i){
                        // printf("\r\nreadPtr:%x\r\n", fileHead.readPtr);
                        // printf("readPtrDiff:%x\r\n", fileHead.readPtr - rdPtrBack);
                        rdPtrBack = fileHead.readPtr;
                        int rd_res = ReadFromFile(&fileHead, buf, 512);
                        int j = 0;
                        for(int i=0;i<512;++i){
                            printf("%.2x ", buf[i]);
                            ++j;
                            if (j == 16) {
                                j = 0;
                                printf("\r\n");
                            }
                        }
                        memset(buf, 0x00, sizeof(buf));
                    }
                    printf("\r\nend\r\n");
                    CloseFile(fileHandle,&fileHead);
                }else{
                    printf("no such file Tapp\r\n");
                }
    #endif

                // chackTimes = 0;
                chackTimes_storefile = 0;
                chackTimes_httpget = 0;
                chackTimes_openfile = 0;
                chackTimes_readfile = 0;
                // getData0ErrorTimes = 0;
                // transfer_times=0;
                getDataLengthSum = 0;
                TaskToClosed(thisTask);
            }

            break;

    default:
        break;
    }

    // printf("DownloadEcuFile-exit...\r\n");

}



//文件下载测试函数
void OtaFileDownloadTest(void){
    
    memset(OtaStateManage.otaDownloadFileParam.fileUrl,0x00,sizeof(OtaStateManage.otaDownloadFileParam.fileUrl));
    OtaStateManage.otaDownloadFileParam.urlLen = 0;

    strcpy((char*)(OtaStateManage.OtaEcuData.OtaParam.companyCode),"123");
    strcpy((char*)(OtaStateManage.OtaEcuData.OtaParam.deviceId),"AC072-7913010");
    strcpy((char*)(OtaStateManage.OtaEcuData.OtaParam.hardV),"hta01");
    strcpy((char*)(OtaStateManage.OtaEcuData.OtaParam.softV),"sta01");
    strcpy((char*)(OtaStateManage.OtaEcuData.OtaParam.targetDevice),"bms");
    //driver file msg
    //part0
    OtaStateManage.OtaEcuData.fileData[1].Addr[0].fileIndex = 0;
    OtaStateManage.OtaEcuData.fileData[1].Addr[0].fileSize = 1234;
    strcpy((char*)(OtaStateManage.OtaEcuData.fileData[1].Addr[0].sunUrl),"driver_01.S19");
    OtaStateManage.OtaEcuData.fileData[1].Addr[0].linkLen = strlen((const char*)(OtaStateManage.OtaEcuData.fileData[1].Addr[0].sunUrl));
    strcpy((char*)(OtaStateManage.OtaEcuData.fileData[1].fatherUrl),"123456");
    OtaStateManage.OtaEcuData.fileData[1].fatherLinkLen = strlen((const char*)(OtaStateManage.OtaEcuData.fileData[1].fatherUrl));

    strcpy((char*)(OtaStateManage.OtaEcuData.fileData[1].fileName),"driver");
    OtaStateManage.OtaEcuData.fileData[1].fileSizeSum = 1234;
    OtaStateManage.OtaEcuData.fileData[1].fileType = OTA_FILE_S19;
    strcpy((char*)(OtaStateManage.OtaEcuData.fileData[1].md5Code),"12345");
    OtaStateManage.OtaEcuData.fileData[1].sliceFileCount = 1;
    //ota file msg
    //part0
    OtaStateManage.OtaEcuData.fileData[2].Addr[0].fileIndex = 0;
    OtaStateManage.OtaEcuData.fileData[2].Addr[0].fileSize = 1234;
    strcpy((char*)(OtaStateManage.OtaEcuData.fileData[2].Addr[0].sunUrl),"driver_01.S19");
    OtaStateManage.OtaEcuData.fileData[2].Addr[0].linkLen = strlen((const char*)(OtaStateManage.OtaEcuData.fileData[2].Addr[0].sunUrl));
    //part1
    OtaStateManage.OtaEcuData.fileData[2].Addr[1].fileIndex = 0;
    OtaStateManage.OtaEcuData.fileData[2].Addr[1].fileSize = 1234;
    strcpy((char*)(OtaStateManage.OtaEcuData.fileData[2].Addr[1].sunUrl),"driver_02.S19");
    OtaStateManage.OtaEcuData.fileData[2].Addr[1].linkLen = strlen((const char*)(OtaStateManage.OtaEcuData.fileData[2].Addr[1].sunUrl));
    //part2
    OtaStateManage.OtaEcuData.fileData[2].Addr[2].fileIndex = 0;
    OtaStateManage.OtaEcuData.fileData[2].Addr[2].fileSize = 1234;
    strcpy((char*)(OtaStateManage.OtaEcuData.fileData[2].Addr[2].sunUrl),"driver_03.S19");
    OtaStateManage.OtaEcuData.fileData[2].Addr[2].linkLen = strlen((const char*)(OtaStateManage.OtaEcuData.fileData[2].Addr[2].sunUrl));
    //part3
    OtaStateManage.OtaEcuData.fileData[2].Addr[3].fileIndex = 0;
    OtaStateManage.OtaEcuData.fileData[2].Addr[3].fileSize = 1234;
    strcpy((char*)(OtaStateManage.OtaEcuData.fileData[2].Addr[3].sunUrl),"driver_04.S19");
    OtaStateManage.OtaEcuData.fileData[2].Addr[3].linkLen = strlen((const char*)(OtaStateManage.OtaEcuData.fileData[2].Addr[3].sunUrl));
    //part4
    OtaStateManage.OtaEcuData.fileData[2].Addr[4].fileIndex = 0;
    OtaStateManage.OtaEcuData.fileData[2].Addr[4].fileSize = 1234;
    strcpy((char*)(OtaStateManage.OtaEcuData.fileData[2].Addr[4].sunUrl),"driver_05.S19");
    OtaStateManage.OtaEcuData.fileData[2].Addr[4].linkLen = strlen((const char*)(OtaStateManage.OtaEcuData.fileData[2].Addr[4].sunUrl));
    //part5
    OtaStateManage.OtaEcuData.fileData[2].Addr[5].fileIndex = 0;
    OtaStateManage.OtaEcuData.fileData[2].Addr[5].fileSize = 1234;
    strcpy((char*)(OtaStateManage.OtaEcuData.fileData[2].Addr[5].sunUrl),"driver_06.S19");
    OtaStateManage.OtaEcuData.fileData[2].Addr[5].linkLen = strlen((const char*)(OtaStateManage.OtaEcuData.fileData[2].Addr[5].sunUrl));

    strcpy((char*)(OtaStateManage.OtaEcuData.fileData[2].fatherUrl),"123456");
    OtaStateManage.OtaEcuData.fileData[2].fatherLinkLen = strlen((const char*)(OtaStateManage.OtaEcuData.fileData[2].fatherUrl));
    strcpy((char*)(OtaStateManage.OtaEcuData.fileData[2].fileName),"ota");
    OtaStateManage.OtaEcuData.fileData[2].fileSizeSum = 1234;
    OtaStateManage.OtaEcuData.fileData[2].fileType = OTA_FILE_S19;
    strcpy((char*)(OtaStateManage.OtaEcuData.fileData[2].md5Code),"12345");
    OtaStateManage.OtaEcuData.fileData[2].sliceFileCount = 1;  
}

void CreatTestInitFlash(void){
    extern tFlashHead FlashHead;
    uint16_t i=0,j=0;
    uint32_t flashData[256]; //系统数据从80（32位）位置开始
    uint32_t FlashHeadData[64];

    // uint32_t block_i=0,blockAddr=0;
    // uint16_t logicBlock=0,badBlock=0;
    // uint32_t pageBuff[512];

    // uint8_t page0[2048],page1[2048],page2[2048];

    // //保留0 1 2页数据
    // GD5F1GQ5_Read_WholePage(0*64+0,page0);
    // GD5F1GQ5_Read_WholePage(0*64+1,page1);
    // GD5F1GQ5_Read_WholePage(0*64+2,page2);

    // GD5F1GQ5_BlockErase(0*64);

    // GD5F1GQ5_WritWholePage(0*64+0,page0);
    // GD5F1GQ5_WritWholePage(0*64+1,page1);
    // GD5F1GQ5_WritWholePage(0*64+2,page2);
   
    // //初始值是1是因为0块被使用了
    // for(block_i=1;block_i<BLOCK_MAX-1;block_i++){
    //     #if WATCH_DOG
    //         IWDT_Feed_Dog();
    //     #endif
    //     //测试阶段先擦一下
    //     //GD5F1GQ5_BlockErase(block_i*64);
    //     //首先获得一个块用于做交换块
    //     if(!FlashHead.swapBlock || FlashHead.swapBlock > 0xffff){
    //         //初始化交换块地址不可能大于最大地址值
    //         FlashHead.swapBlock = block_i*64;
    //         continue;
    //     }
    //     if(!GetBadBlock(block_i)){
    //         //不是坏块登记到逻辑映射表中
    //         blockAddr = (block_i*64)|0xc0000000;
    //         LogicBlockRegister(blockAddr,logicBlock);  //地址高两位用于标识，31自由块和30垃圾块
    //         //LOG_DBG("get %d block is:%x\n",logicBlock,blockAddr);
    //         logicBlock++;
    //     }else{
    //         BadBlockRegister(block_i*64,badBlock);
    //         badBlock++;    
    //     }
    // }
    // //将初始化数据保存到flash中
    // FlashHead.blockCount = logicBlock;
    // FlashHead.blockSum = logicBlock;
    // FlashHead.badBlockManageTable = BAD_BLOCK_TABLE_ADDR;
    // FlashHead.blockManageTable = LOGIC_TABLE_ADDR;
    // FlashHead.fileManageTable = MENU_TABLE_ADDR;
    // FlashHead.lastLogicBlock = 0;

    // // //保存到flash中
    // CloseInterupt();
	// FLASH_READCODE_fun(SYS_DataAddr,flashData,256);
    // memcpy(FlashHeadData,&FlashHead,sizeof(FlashHead));

	// for(i=FlashHeadAddr,j=0;i<FlashHeadAddr+10;i++,j++){
    //     flashData[i] = FlashHeadData[j];
    // }

	// FLASH_Wipe_Configuration_RAM(FLASH_WIPE_CODE_PAGE,SYS_DataAddr);
	// FLASH_PageWrite_fun(SYS_DataAddr,flashData,128);

    // OpenInterupt();
    FlashHead.blockCount = 1021;
    FlashHead.blockSum = 1021;
    FlashHead.badBlockManageTable = BAD_BLOCK_TABLE_ADDR;
    FlashHead.blockManageTable = LOGIC_TABLE_ADDR;
    FlashHead.fileManageTable = MENU_TABLE_ADDR;
    FlashHead.lastLogicBlock = 0;

    // //保存到flash中
    CloseInterupt();
	FLASH_READCODE_fun(SYS_DataAddr,flashData,256);
    memcpy(FlashHeadData,&FlashHead,sizeof(FlashHead));
	for(i=FlashHeadAddr,j=0;i<FlashHeadAddr+10;i++,j++){
        flashData[i] = FlashHeadData[j];
        LOG_DBG("flashData[%d]:%x,FlashHeadData:%x\n",i,flashData[i],FlashHeadData[j]);
    }
	FLASH_Wipe_Configuration_RAM(FLASH_WIPE_CODE_PAGE,SYS_DataAddr);
	FLASH_PageWrite_fun(SYS_DataAddr,flashData,128);
    OpenInterupt();



}

//升级测试为了不频繁升级，使用手动flash操作
void CreatTestFileData(void){
    OtaStateManage.downloadFileState[1].fileIndex = 1;//CreatFileHandle("drif",0);
    OtaStateManage.downloadFileState[1].downloadEcuFileSizeSum = 1234;
    OtaStateManage.downloadFileState[1].fileState = 1;
    LOG_DBG("creat file drif index:%d,file size:%d\n",OtaStateManage.downloadFileState[1].fileIndex,OtaStateManage.downloadFileState[1].downloadEcuFileSizeSum);
    OtaStateManage.downloadFileState[2].fileIndex = 2;//CreatFileHandle("otaf",0);
    OtaStateManage.downloadFileState[2].downloadEcuFileSizeSum = 1234;
    OtaStateManage.downloadFileState[2].fileState = 1;
    LOG_DBG("creat file drif index:%d,file size:%d\n",OtaStateManage.downloadFileState[2].fileIndex,OtaStateManage.downloadFileState[2].downloadEcuFileSizeSum);
}

void OtaFileDownTest(void){
    tFileHead fileHead;
    uint8_t dataBuff[1024];
    uint16_t dataLen=0;
    uint16_t i=0;
    uint8_t fileIndex=0xff;
    fileIndex = CheckFileName("drif");
    LOG_DBG("**open driver file:index:%d,find file index:%d\r\n",OtaStateManage.downloadFileState[OTA_DRIVER_FILE].fileIndex,fileIndex);

    fileHead = OpenFile(OtaStateManage.downloadFileState[OTA_DRIVER_FILE].fileIndex);
    memset(dataBuff,0x00,1024);
    for (i = 0; i < 20; i++)
    {
        dataLen = ReadFromTextOneLine(&fileHead,dataBuff,1024);
        LOG_DBG("**readPtr:%d,writePtr:%d\r\n",fileHead.readPtr,fileHead.writePtr);
        LOG_DBG("**file[%d]:%s\r\n",dataLen,dataBuff);
    }
    CloseFile(OtaStateManage.downloadFileState[OTA_DRIVER_FILE].fileIndex,&fileHead);
    
    fileHead.readPtr = 0;
    fileHead.writePtr = 0;

    fileHead = OpenFile(OtaStateManage.downloadFileState[OTA_DRIVER_FILE].fileIndex);
    memset(dataBuff,0x00,1024);
    for (i = 0; i < 20; i++)
    {
        dataLen = ReadFromTextOneLine(&fileHead,dataBuff,1024);
        LOG_DBG("**readPtr:%d,writePtr:%d\r\n",fileHead.readPtr,fileHead.writePtr);
        LOG_DBG("**file[%d]:%s\r\n",dataLen,dataBuff);
    }
    CloseFile(OtaStateManage.downloadFileState[OTA_DRIVER_FILE].fileIndex,&fileHead);

    // fileHead = OpenFile(OtaStateManage.downloadFileState[OTA_DRIVER_FILE].fileIndex);
    // memset(dataBuff,0x00,1024);
    // for (i = 0; i < 81; i++)
    // {
    //     dataLen = ReadFromTextOneLine(&fileHead,dataBuff,1024);
    //     LOG_DBG("**read driver file[%d]:%s\r\n",dataLen,dataBuff);
    // }
    // CloseFile(OtaStateManage.downloadFileState[OTA_DRIVER_FILE].fileIndex,&fileHead);
    // LOG_DBG("**open ota file:index-%d\r\n",OtaStateManage.downloadFileState[OTA_OTA_FILE].fileIndex);
    // fileHead = OpenFile(OtaStateManage.downloadFileState[OTA_OTA_FILE].fileIndex);
    // memset(dataBuff,0x00,1024);
    // for (i = 0; i < 1000; i++)
    // {
    //     dataLen = ReadFromTextOneLine(&fileHead,dataBuff,1024);
    //     LOG_DBG("**read ota file[%d]:%s\r\n",dataLen,dataBuff);
    // }
    // CloseFile(OtaStateManage.downloadFileState[OTA_OTA_FILE].fileIndex,&fileHead);   
}


void OtaFileDownTestReadAll(void){
    tFileHead fileHead;
    uint8_t dataBuff[1024];
    uint16_t dataLen=0;
    uint16_t i=0;
    uint8_t fileIndex=0xff;
    fileIndex = CheckFileName("drif");
    LOG_DBG("**open driver file:index:%d,find file index:%d\r\n",OtaStateManage.downloadFileState[OTA_DRIVER_FILE].fileIndex,fileIndex);

    // fileHead = OpenFile(OtaStateManage.downloadFileState[OTA_DRIVER_FILE].fileIndex);
    // memset(dataBuff,0x00,1024);
    // while (1){
    //     dataLen = ReadFromTextOneLine(&fileHead,dataBuff,1024);
    //     LOG_DBG("**readPtr:%d,writePtr:%d\r\n",fileHead.readPtr,fileHead.writePtr);
    //     if(dataLen == 0 || dataLen == 0xffff){
    //         LOG_DBG("**get file error[%d]:%s\r\n",dataLen,dataBuff);
    //         break;
    //     }else{
    //         LOG_DBG("**file[%d]:%s\r\n",dataLen,dataBuff);
    //     }
    // }
    // CloseFile(OtaStateManage.downloadFileState[OTA_DRIVER_FILE].fileIndex,&fileHead);
    
    // fileHead.readPtr = 0;
    // fileHead.writePtr = 0;

    fileHead = OpenFile(OtaStateManage.downloadFileState[OTA_OTA_FILE].fileIndex);
    while (1)
    {
        memset(dataBuff,0x00,1024);
        dataLen = ReadFromTextOneLine(&fileHead,dataBuff,1024);
        LOG_DBG("**readPtr:%d,writePtr:%d\r\n",fileHead.readPtr,fileHead.writePtr);
        if(dataLen == 0 || dataLen == 0xffff){
            LOG_DBG("**get file error[%d]:\r\n",dataLen);
            break;
        }else{
            if(dataLen<60)
                LOG_DBG("**file[%d]:%s\r\n",dataLen,dataBuff);
            else{
                LOG_DBG("**file[%d]:%s\r\n",dataLen,dataBuff);
                LOG_DBG("**get one line maby error,not check end:\r\n");
                for (i = 0; i < dataLen; i++)
                {
                    LOG_DBG("%d ",dataBuff[i]);
                }
                LOG_DBG("\r\n ");
            }
        }
    }
    CloseFile(OtaStateManage.downloadFileState[OTA_OTA_FILE].fileIndex,&fileHead);  
}

//进入文件下载模式
uint8_t OTA_InFileDownloadMod(void)
{
    CloseInterupt_CAN();
    return 0;
}

uint8_t OTA_OutFileDownload(void)
{
    OpenInterupt_CAN();
    return 0;
}

//进入升级模式函数
static uint8_t OTA_InUpgradeMode(void){
    SetSysRunState(SYS_UPGRADE);
    Wirelesess_GPS_open_off(0);
    delay_ms(10);
    SetSysNeedOnlineState(false);
    // GPT_CMPL
    // GPTIM_Set_Period(T4_SFR,4000);	 //4G模块某些下载帧间隔超过2ms,重新设置接收完成定时器时间为4ms。【必须】
    return 0;
}

//退出升级模式函数
static uint8_t OTA_OutOTAUpgradeMode(void){
    SetSysRunState(SYS_NORMAL);
    Wirelesess_GPS_open_off(2);
    delay_ms(10);
    //退出升级模式
    SetSysNeedOnlineState(true);
    // GPTIM_Set_Period(T4_SFR,2000);   GPT_CMPL
    return 0;
}






